using System;
using System.Collections.Generic;
using System.Linq;
using Castle.DynamicProxy;
using Microsoft.Practices.ObjectBuilder2;

namespace UniAspect.Aspect
{
    public class ProxyFactory : IBuildPlanPolicy
    {
        private readonly IList<IAspect> _interceptors = new List<IAspect>();
        private readonly Type _originalType;
        private readonly ProxyGenerator _generator = new ProxyGenerator();
        private readonly IBuildPlanCreatorPolicy _constructorBuildPolicy;

        public ProxyFactory(Type originalType, IBuildPlanCreatorPolicy constructorBuildPolicy)
        {
            _originalType = originalType;
            _constructorBuildPolicy = constructorBuildPolicy;
        }

        public ProxyFactory()
        {
        }

        public IList<IAspect> Interceptors
        {
            get { return _interceptors; }
        }

        public void BuildUp(IBuilderContext context)
        {
            if(context.Existing != null)
                return;

            Type typeToBuild = BuildKey.GetType(context.BuildKey);
            if(_originalType == null)
            {
                context.Existing = _generator.CreateClassProxy(typeToBuild, _interceptors.ToArray());
            }
            else
            {
                IBuildPlanPolicy plan = _constructorBuildPolicy.CreatePlan(context, context.BuildKey);
                context.Policies.Set(plan, context.BuildKey);
                plan.BuildUp(context);

                context.Existing = _generator.CreateInterfaceProxyWithTarget(
                        _originalType, context.Existing, _interceptors.ToArray());
            }
        }
    }
}